package top.healthylife.gateway.mgr.controller;//package com.hare.service.gateway.controller;
//
//import cn.hutool.core.codec.Base64Decoder;
//import cn.hutool.core.date.DatePattern;
//import cn.hutool.core.date.LocalDateTimeUtil;
//import cn.hutool.core.lang.Dict;
//import cn.hutool.core.net.URLDecoder;
//import cn.hutool.core.util.ObjectUtil;
//import cn.hutool.core.util.StrUtil;
//import cn.hutool.crypto.SecureUtil;
//import cn.hutool.json.JSONUtil;
//import com.alibaba.fastjson.JSONObject;
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.basics.data.redisdata.RedisUtil;
//import com.basics.exception.BusinessException;
//import com.basics.log.annotation.Log;
//import com.basics.log.utils.IpUtil;
//import com.basics.utils.IdGenerator;
//import com.basics.utils.PageUtil;
//import com.basics.utils.R;
//import com.basics.utils.SystemThreadLocal;
//import com.hare.service.dto.base.SystemInfoDto;
//import com.hare.service.function.callapi.cons.SystemCons;
//import com.hare.service.function.callapi.po.*;
//import com.hare.service.function.callapi.utils.SecretJsonUtils;
//import com.hare.service.function.callapi.vo.ApiReqRestVo;
//import com.hare.service.gateway.component.ApiComponent;
//import com.hare.service.gateway.component.GatewaySaveLogComponent;
//import com.hare.service.gateway.constant.ApiGatewayConstant;
//import com.hare.service.gateway.service.GatewayAccountService;
//import com.hare.service.gateway.service.GatewayLogService;
//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiOperation;
//import lombok.AllArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.web.bind.annotation.*;
//import org.springframework.web.client.RestTemplate;
//
//import java.nio.charset.Charset;
//import java.time.LocalDateTime;
//import java.util.LinkedHashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.Optional;
//import java.util.function.Predicate;
//import java.util.stream.Collectors;
//
///**
// * @author GaoZexi
// * @date 2020/3/20 11:56
// */
//@Api(tags = "数据网关服务网关接口")
//@Slf4j
//@RestController
//@RequestMapping
//@AllArgsConstructor
//public class ApiInterfaceRuleController {
//    ApiComponent apiComponent;
//    RestTemplate restTemplate;
//    GatewayAccountService gatewayAccountService;
//    GatewaySaveLogComponent gatewaySaveLogComponent;
//    GatewayLogService gatewayLogService;
//
//
//
//    @ApiOperation("服务商列表")
//    @GetMapping("/platform/list")
//    public R<List<SystemPo>> platform(@RequestParam(required = false) String systemName) {
//        List<SystemPo> list = RedisUtil.list(SystemCons.platformKey(), SystemPo.class);
//        if (ObjectUtil.isNotEmpty(systemName)) {
//            list = list.stream().filter(e -> e.getSystemName().contains(systemName)).collect(Collectors.toList());
//        }
//        return R.ok(list);
//    }
//
//
//    @ApiOperation("服务商账户配置信息")
//    @GetMapping("/account/config/template/{shortName}")
//    @SuppressWarnings("unchecked")
//    public R<List<SystemInfoDto>> accountConfigTemplate(@PathVariable String shortName) {
//        SystemPo systemPo = apiComponent.checkSystemPo(shortName);
//        return restTemplate.getForObject(SystemCons.getSystemConfigUrl(systemPo.getApplicationName()), R.class);
//    }
//
//
//    @ApiOperation("接口列表(分页)")
//    @GetMapping("/interfaces/list")
//    public R<Page<ParentApiPo>> interfaces(@RequestParam(required = false) String shortName,
//                                           @RequestParam(required = false) String apiName,
//                                           @RequestParam(required = false, defaultValue = "1") long current,
//                                           @RequestParam(required = false, defaultValue = "10") long size
//    ) {
//        //查询所有
//        List<SystemPo> list = RedisUtil.list(SystemCons.platformKey(), SystemPo.class);
//        //过滤存活的项目
//        Predicate<SystemPo> filter = e -> RedisUtil.exists(SystemCons.systemHealthKey(e.getShortName()));
//        List<SystemPo> collect = list.stream().filter(filter)
//                .map(e -> apiComponent.checkSystemPo(e.getShortName())).collect(Collectors.toList());
//        List<ParentApiPo> allApis = collect.stream()
//                .filter(e -> ObjectUtil.isEmpty(shortName) || e.getShortName().equals(shortName))
//                .flatMap(e -> e.getApis().stream())
//                .collect(Collectors.toList());
//        if (ObjectUtil.isNotEmpty(apiName)) {
//            allApis = allApis.stream().filter(e -> e.getApiName().contains(apiName)).collect(Collectors.toList());
//        }
//        Page<ParentApiPo> page = new Page<>(current, size);
//        page.setTotal(allApis.size());
//        page.setRecords(PageUtil.startPage(allApis, page.getCurrent(), page.getSize()));
//        return R.ok(page);
//    }
//
//
//
//    @ApiOperation("服务商详情")
//    @GetMapping("/systemInfo/{shortName}")
//    public R<SystemPo> getSystemInfo(@PathVariable String shortName) {
//        return R.ok(apiComponent.checkSystemPo(shortName));
//    }
//
//    //
//    //@Log
//    //@ApiOperation("接口的入参和出参的class")
//    //@GetMapping("/api/cls")
//    //R<List<String>> getClasses(@RequestParam String shortName, @RequestParam String apiName) {
//    //    ParentApiPo apiPo = apiComponent.checkSystemPo(shortName).getApis().stream()
//    //            .filter(e -> e.getApiName().equals(apiName))
//    //            .findAny().orElseThrow(() -> new BusinessException("API未找到"));
//    //    return R.ok(new ArrayList<String>() {{
//    //        add(apiPo.getCls());
//    //        add(apiPo.getResCls());
//    //    }});
//    //}
//    //
//    //@Log
//    //@ApiOperation("获取接口API的实体cls")
//    //@GetMapping("/cls")
//    //R<String> getCls(@RequestParam String shortName, @RequestParam String apiName) {
//    //    String cls = apiComponent.checkSystemPo(shortName).getApis().stream().filter(e -> e.getApiName().equals(apiName)).findAny().orElseThrow(() -> new BusinessException("API未找到")).getCls();
//    //    return R.ok(cls);
//    //}
//
//
//    @ApiOperation("模糊检索API返回参数")
//    @GetMapping("/search")
//    public R<?> search(@RequestParam String shortName, @RequestParam String keyword) {
//        //根据接口名称,和服务名进行数据返回
//        //获取所有的第三方的服务名
//        String redisKey = "interface:api:gateway:" + shortName;
//        //匹配第方三方在线的服务
//        //获取所有在线的服务名
//        SystemPo systemPo = Optional.ofNullable(shortName)
//                .map(e -> RedisUtil.get(redisKey, SystemPo.class))
//                .orElseThrow(() -> new BusinessException("没有此服务"));
//        //取出对应的服务名,请求具体的微服务
//        return restTemplate.getForObject(String.format("http://%s/search?searchName=%s", systemPo.getApplicationName(), keyword), R.class);
//    }
//
//
//    @ApiOperation("根据接口名获取出参入参")
//    @GetMapping("/api/params")
//    @SuppressWarnings("unchecked")
//    public R<ApiReqRestVo> apiParams(@RequestParam String apiName, @RequestParam String shortName) {
//        //获取服务简称映射的服务名,请求具体的微服务
//        SystemPo systemPo = apiComponent.checkSystemPo(shortName);
//        String appName = systemPo.getApplicationName();
//        return restTemplate.getForObject(String.format("http://%s/api?apiName=%s", appName,
//                apiName), R.class);
//    }
//
//
//    @ApiOperation("接口请求参数")
//    @GetMapping("/interfaces/{shortName}/{apiName}")
//    public R<List<ApiParameterPo>> getInterfaces(@PathVariable String shortName, @PathVariable String apiName) {
//        //直接获取缓存的东西。
//        SystemPo systemPo = apiComponent.checkSystemPo(shortName);
//        ParentApiPo parentApiPo = systemPo.getApis().stream()
//                .filter(e -> e.getApiName().equals(apiName))
//                .findAny()
//                .orElseThrow(() -> new BusinessException("接口不存在"));
//        List<ApiParameterPo> parameters = parentApiPo.getParameters();
//        return R.ok(parameters);
//    }
//
//
//    /**
//     * 直接调用第三方接口
//     *
//     * @param reqParams       请求接口需要的入参 格式为 map对象 转换为json,然后使用secret作为加密秘钥 用Aes加密,在使用Base64格式编码放在请求体中
//     * @param apiName         接口名 如果包含中文,需要URL_ENCODE
//     * @param applicationName 调用方名称,如果包含中文 需要URL_ENCODE
//     * @param secret          secret 秘钥 base64编码后放入链接
//     * @return 三方接口返回的数据
//     */
//    @ApiOperation("调用接口服务网关(外部)")
//
//    @PostMapping("/api/invoke/{secret}")
//    @SuppressWarnings("unchecked")
//    public R<?> invokeApiData(@RequestHeader("apiName") String apiName,
//                              @RequestHeader("applicationName") String applicationName,
//                              @RequestHeader(value = "periodValidity", required = false) Long periodValidity,
//                              @RequestBody Map<String, Object> reqParams, @PathVariable String secret) {
//
//        String apiNameDecode;
//        String applicationNameDecode;
//        String reallySecret;
//        //1.base64解码秘钥 拿到apiName,secret 的明文
//        try {
//            applicationNameDecode = new String(Base64Decoder.decode(applicationName));
//            apiNameDecode = new String(Base64Decoder.decode(apiName));
//            byte[] secretDecode = Base64Decoder.decode(secret);
//            reallySecret = new String(secretDecode);
//        } catch (Exception e) {
//            throw new BusinessException("请求参数解码异常");
//        }
//        //2.根据secret查询帐号信息,理论上只允许存在一个,租户唯一;
//        GatewayAccountPo secretPo;
//        try {
//            secretPo = gatewayAccountService.getOne(Wrappers.query(new GatewayAccountPo().setSecret(reallySecret)));
//            if (secretPo == null) {
//                return R.failed(10001, "未查询到该账号信息,请检查秘钥");
//            }
//        } catch (Exception e) {
//            String message = StrUtil.format("查询数据网关账户信息异常,异常信息:{}(Maybe caused by duty data),请联系管理员", e.getMessage());
//            log.error(message);
//            return R.failed(10001, message);
//        }
//        applicationNameDecode = StrUtil.format("http调用:{}", applicationNameDecode);
//        //直接请求接口网关
//        String shortName = secretPo.getShortName();
//        try {
//            R<?> r = results(apiNameDecode, reqParams, reallySecret, periodValidity, applicationNameDecode);
//            if (r.getCode() == 0) {
//                Object data1 = r.getData();
//                if (data1 instanceof LinkedHashMap) {
//                    log.info("r.getData() 结果类型为 LinkedHashMap");
//                    LinkedHashMap<String, Object> linkedHashMap = (LinkedHashMap<String, Object>) data1;
//                    linkedHashMap.remove("cls");
//                } else if (data1 instanceof JSONObject) {
//                    log.info("r.getData() 结果类型为 JSONObject");
//                    JSONObject data = (JSONObject) data1;
//                    data.remove("cls");
//                } else {
//                    Class<?> aClass = data1.getClass();
//                    log.info("r.getData() 结果类型为 {}", aClass.getSimpleName());
//                }
//            }
//            return r;
//        } catch (Exception e) {
//            String message = StrUtil.format("请求数据网关异常,异常信息:{}", e.getMessage());
//            return R.failed(10002, message);
//        }
//
//    }
//
//    //@Log
//    @ApiOperation("调用接口服务网关(内部)")
//    @PostMapping("/api/results/{apiName}")
//    public R<?> results(
//            @PathVariable String apiName,
//            @RequestBody Map<String, Object> data,
//            @RequestHeader("secret") String secret,
//            @RequestHeader(value = "periodValidity", required = false) Long periodValidity,
//            @RequestHeader(value = "applicationName", required = false) String applicationName) {
//        long l1 = System.currentTimeMillis();
//        apiName = URLDecoder.decode(apiName, Charset.defaultCharset());
//        applicationName = URLDecoder.decode(applicationName, Charset.defaultCharset());
//        //对数据进行加密
//        String string = JSONObject.toJSONString(data);
//        String md5 = SecureUtil.md5(string + apiName + secret);
//        //检查是否存在这个secret帐号是否存在
//        GatewayAccountPo gatewayAccountPo = apiComponent.checkSecret(secret);
//        String shortName = gatewayAccountPo.getShortName();
//        log.info("调用接口服务网关的请求参数:接口名,{},平台名称:{},帐号,{},有效时间,{},md5值,{}", apiName, shortName, secret, periodValidity, md5);
//        //初始化日志信息
//        GatewayLogPo gatewayLogPo = GatewayLogPo.builder()
//                .md5(md5)
//                //流水号
//                .groupNo(IdGenerator.getId())
//                //调用方服务名
//                .applicationName(applicationName)
//                .requestData(string)
//                .originReqData(null)
//                .returnData(null)
//                //非命中缓存
//                //接口名称
//                .apiName(apiName)
//                .secret(secret)
//                //接口简称
//                .shortName(shortName)
//                //开始时间
//                .createTime(LocalDateTime.now())
//                //ip
//                .ip(IpUtil.getIp())
//                .build();
//        //如果未传入有效时间,则获取各个数据源默认的有效时间
//        if (periodValidity != null) {
//            gatewayLogPo.setPeriodValidity(periodValidity + "A");
//        } else {
//            periodValidity = ApiGatewayConstant.getDefaultPeriodValidity(shortName, gatewayLogPo);
//        }
//        //判断有效时间
//        if (periodValidity >= 0) {
//            //检查缓存是否存在此数据
//            Object cache = apiComponent.cache(periodValidity, shortName, apiName, md5);
//            //如果缓存中没有数据,则走真实接口
//            if (Optional.ofNullable(cache).isPresent()) {
//                log.info("命中缓存数据");
//                gatewayLogPo.setHitCache(true);
//                gatewayLogPo.setReturnData(JSONObject.toJSONString(cache));
//                //请求结果成功
//                gatewayLogPo.setStatus(true);
//                gatewayLogPo.setFinishTime(LocalDateTime.now());
//                gatewaySaveLogComponent.saveLog(gatewayLogPo);
//                long l3 = System.currentTimeMillis();
//                log.info("网关耗时" + (l3 - l1));
//                //触发日志保存
//                return JSONObject.parseObject(JSONObject.toJSONString(cache), R.class);
//            }
//            log.info("缓存中没有数据，走真实接口");
//        }
//        log.info("缓存有效时间<0,实时查询三方接口数据");
//        //检查下游服务是否存在，如果存在，直接返回下游系统基础信息
//        SystemPo systemPo = apiComponent.checkSystemPo(shortName);
//
//        //请求具体的微服务
//        String secretJson = gatewayAccountPo.getSecretJson();
//        Object o = apiComponent.callService(secret, apiName, SecretJsonUtils.encryptBase64(secretJson), systemPo.getApplicationName(), data, gatewayLogPo);
//        if (Optional.ofNullable(o).isPresent()) {
//            return R.ok(o);
//        } else {
//            R resultDtoR;
//            String exception = SystemThreadLocal.get("exception");
//            SystemThreadLocal.remove("exception");
//            if (exception != null) {
//                resultDtoR = R.failed(exception);
//            } else {
//                resultDtoR = R.failed("接口调用失败,请联系管理员");
//            }
//            return resultDtoR.setCode(5001);
//        }
//    }
//
//
//    @ApiOperation("根据服务名获取缓存中最新的一条数据")
//    @PostMapping("/cache/{shortName}/{apiName}")
//    public R<?> cache(@PathVariable String shortName, @PathVariable String apiName) {
//        //查询缓存中最新的那一条数据
//        Object cache = apiComponent.cache(0L, shortName, apiName, null);
//        if (Optional.ofNullable(cache).isPresent()) {
//            log.info("命中缓存数据");
//            //触发日志保存
//            return R.ok(cache);
//        }
//        return R.failed("没有找到缓存数据");
//    }
//
//
//    @ApiOperation("校验账号是否可用")
//    @PostMapping("/check/enable/{shortName}/{secret}")
//    public R<Boolean> checkEnable(@PathVariable String shortName, @PathVariable String secret, @RequestBody Map jsonMap) {
//        Dict dict = apiComponent.checkSecretEnable(JSONObject.toJSONString(jsonMap), secret, shortName);
//        Boolean enable = (Boolean) dict.get("enable");
//        String msg = dict.get("msg").toString();
//        return enable ? R.ok(true, "账号可用") : R.failed(false, msg);
//    }
//
//
//    /**
//     * 查询数据网关日志
//     * 查询条件
//     * <ul>
//     *     <li>id查询</li>
//     *     <li>接口名称查询(=)</li>
//     *     <li>数据源简称(=)</li>
//     *     <li>调用方名称(=)</li>
//     *     <li>开始时间-结束时间 区间查询</li>
//     *     <li>是否查看缓存(=)</li>
//     *     <li>秘钥查询(=)</li>
//     *     <li>入参查询(like)</li>
//     *     <li>流水号查询(=)</li>
//     * </ul>
//     *
//     * @return 分页查询对象
//     */
//    @ApiOperation("日志分页查询")
//    @PostMapping("/log/page")
//    R<Page<GatewayLogPo>> getGatewayLogByPage(@RequestBody GatewayLogByPage gatewayLogByPage) {
//        GatewayLogPo gatewayLogPo = gatewayLogByPage.getGatewayLogPo();
//        Page<GatewayLogPo> page = gatewayLogByPage.getPage();
//        LambdaQueryWrapper<GatewayLogPo> gatewayLogPoLambdaQueryWrapper = Wrappers.<GatewayLogPo>lambdaQuery();
//        LocalDateTime startTime = gatewayLogPo.getCreateTime();
//        LocalDateTime endTime = gatewayLogPo.getFinishTime();
//        LocalDateTime defaultStartTime = LocalDateTimeUtil.parse("2000-01-01 00:00:00", DatePattern.NORM_DATETIME_PATTERN);
//        LocalDateTime defaultEndTime = LocalDateTimeUtil.parse("2099-01-01 00:00:00", DatePattern.NORM_DATETIME_PATTERN);
//        boolean startFlag = ObjectUtil.isEmpty(startTime);
//        boolean endFlag = ObjectUtil.isEmpty(endTime);
//        gatewayLogPoLambdaQueryWrapper
//                .eq(StrUtil.isNotBlank(gatewayLogPo.getId()), GatewayLogPo::getId, gatewayLogPo.getId())
//                .eq(StrUtil.isNotBlank(gatewayLogPo.getApiName()), GatewayLogPo::getApiName, gatewayLogPo.getApiName())
//                .eq(StrUtil.isNotBlank(gatewayLogPo.getShortName()), GatewayLogPo::getShortName, gatewayLogPo.getShortName())
//                .eq(StrUtil.isNotBlank(gatewayLogPo.getApplicationName()),
//                        GatewayLogPo::getApplicationName, gatewayLogPo.getApplicationName())
//                .between(!startFlag || !endFlag, GatewayLogPo::getCreateTime,
//                        startFlag ? defaultStartTime : startTime, endFlag ? defaultEndTime : endTime)
//                .eq(ObjectUtil.isNotEmpty(gatewayLogPo.getHitCache()), GatewayLogPo::getHitCache, gatewayLogPo.getHitCache())
//                .eq(ObjectUtil.isNotEmpty(gatewayLogPo.getHitCache()), GatewayLogPo::getHitCache, gatewayLogPo.getHitCache())
//                .eq(ObjectUtil.isNotEmpty(gatewayLogPo.getSecret()), GatewayLogPo::getSecret, gatewayLogPo.getSecret())
//                .like(ObjectUtil.isNotEmpty(gatewayLogPo.getRequestData()), GatewayLogPo::getRequestData, gatewayLogPo.getRequestData())
//                .eq(ObjectUtil.isNotEmpty(gatewayLogPo.getNo()), GatewayLogPo::getNo, gatewayLogPo.getNo())
//                .orderByDesc(GatewayLogPo::getCreateTime);
//        try {
//            return R.ok(gatewayLogService.page(page, gatewayLogPoLambdaQueryWrapper));
//        } catch (Exception e) {
//            log.error(e.getMessage());
//            throw new BusinessException("日志查询异常");
//        }
//    }
//
//    //public static void main(String[] args) {
//    //    //外部调用数据网关接口示例
//    //    //String url = "http://localhost:30100/api/invoke";
//    //    String url = "https://dcode-test.cguarantee.com/service-interface-gateway/api/invoke";
//    //    //以下参数向平台获取
//    //    String apiName = "失信人[843]";
//    //    String applicationName = "新金控-风控模块-demo";
//    //    /**
//    //     * dev:c2bd37c298c9403e9fd2464b36e01d5b   tyc:c2bd37c298c9403e9fd2464b36e01d5b
//    //     * sit:c27805cf4cfb40669ac2c6157f09371e
//    //     * uat:f791c844b3734976b72decf6f6a153e8   //c2bd37c298c9403e9fd2464b36e01d5b
//    //     * pro:f5cefd736d754d3eaeef73eca8e8e9bd
//    //     */
//    //    String secret = "f791c844b3734976b72decf6f6a153e8"; //jck-sit
//    //    //String secret = "c2bd37c298c9403e9fd2464b36e01d5b";
//    //    String aesKey = "f791c844b3734976b72decf6f6a153e8";
//    //    //String aesKey = "c2bd37c298c9403e9fd2464b36e01d5b";
//    //
//    //    //1.接口名,secret base64编码
//    //    String apiNameEncode = Base64Encoder.encode(apiName);
//    //    String applicationNameEncode = Base64Encoder.encode(applicationName);
//    //    String secretEncode = Base64Encoder.encode(secret);
//    //    //2.参数加密
//    //    //{"id": "530325199207261151", "name": "耿红先", "phone": "13099903997", "idCard": "530325199207261151", }
//    //    //"mobile": "13099903997", "idNumber": "530325199207261151", "accountName": "耿红先", "accountMobile": "13099903997"
//    //    Map<String, Object> map = new HashMap<>(4);
//    //    //map.put("id", "530325199207261151");
//    //    //map.put("idCard", "530325199207261151");
//    //    //map.put("idNumber", "530325199207261151");
//    //    //map.put("accountName", "耿红先");
//    //    //map.put("name", "耿红先");
//    //    //map.put("accountMobile", "13099903997");
//    //    //map.put("mobile", "13099903997");
//    //    map.put("name", "重庆进出口融资担保有限公司");
//    //    map.put("keyword", "重庆进出口融资担保有限公司");
//    //    String json = JSONObject.toJSONString(map);
//    //    //2.1使用秘钥对参数加密
//    //    SecretKey secretKey = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue(), aesKey.getBytes());
//    //    AES aes = SecureUtil.aes(secretKey.getEncoded());
//    //    String reqParams = aes.encryptBase64(json);
//    //    String encodeParam;
//    //    try {
//    //        encodeParam = URLEncoder.encode(reqParams, "UTF-8");
//    //    } catch (UnsupportedEncodingException e) {
//    //        throw new BusinessException("参数编码失败");
//    //    }
//    //    //2.2使用Base64编码
//    //    String responseBody = HttpUtil.createPost(url + "/" + secretEncode)
//    //            .header("apiName", apiNameEncode)
//    //            .header("applicationName", applicationNameEncode)
//    //            .body(encodeParam).execute().body();
//    //    System.out.println("apiName1 = " + aes.decryptStr(responseBody));
//    //}
//}
